#include "enetwork.h"
#include <QEventLoop>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QHttpMultiPart>
#include <QHttpPart>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include "mylogger.h"

using namespace ns_yht;

QString ENetwork::token = QStringLiteral("");
bool ENetwork::networkStatus = false;

#define TOKENHEADNAME QByteArrayLiteral("token")

ENetwork::ENetwork()
{
}

QNetworkAccessManager *ENetwork::getManager()
{
    static QNetworkAccessManager *globalManager = nullptr;
    if (!globalManager)
        globalManager = new QNetworkAccessManager;
    return globalManager;
}

void ENetwork::Post(QNetworkAccessManager *manage, const QByteArray &content, const QString &url, bool needAuthenticated)
{
    int contentLength = content.length();
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
    request.setHeader(QNetworkRequest::ContentLengthHeader, contentLength);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    manage->post(request, content);
}

QNetworkReply *ENetwork::Post(const QByteArray &content, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return Post(getManager(), content, url, httpTypeName, httpTypeValue, needAuthenticated);
}

QNetworkReply *ENetwork::PostWithJson(const QByteArray &json, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return PostWithJson(getManager(), json, url, httpTypeName, httpTypeValue, needAuthenticated);
}

QNetworkReply *ENetwork::PostFile(QMap<QString, QString> files, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return PostFile(getManager(), files, url, httpTypeName, httpTypeValue, needAuthenticated);
}

QNetworkReply *ENetwork::Get(const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return Get(getManager(), url, httpTypeName, httpTypeValue, needAuthenticated);
}

QNetworkReply *ENetwork::Delete(const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return Delete(getManager(), url, httpTypeName, httpTypeValue, needAuthenticated);
}

QNetworkReply *ENetwork::put(const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    return put(getManager(), url, httpTypeName, httpTypeValue, needAuthenticated);
}

bool ENetwork::checkReplyError(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NetworkError::NoError)
        return false;

    if (GLOG)
        GLOG->info("ENetwork::checkReplyError:  {} {}", reply->url().toString().toStdString(), QString::number(reply->error()).toStdString());

    reply->deleteLater();
    return true;
}

bool ENetwork::checkRootError(const QJsonObject &root, const QString &remark)
{
    if (root.contains("errorcode") && root.value("errorcode").toInt() != 0)
    {
        if (GLOG)
        {
            if (root.contains("reason"))
                GLOG->info("http request error! {} , errorcode:{} ,reason:{}", remark.toStdString(), root.value("errorcode").toInt(), root.value("reason").toString().toStdString());
            else
                GLOG->info("http request error! {} , errorcode:{}", remark.toStdString(), root.value("errorcode").toInt());
        }
        return true;
    }
    if (!root.contains("result"))
    {
        if (GLOG)
            GLOG->info("http request error! {} , no [result]", remark.toStdString());
        return true;
    }
    return false;
}

QNetworkReply *ENetwork::Post(QNetworkAccessManager *manage, const QByteArray &content, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    int contentLength = content.length();
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded;charset=UTF-8"));
    request.setHeader(QNetworkRequest::ContentLengthHeader, contentLength);
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->post(request, content);
}

QNetworkReply *ENetwork::PostWithJson(QNetworkAccessManager *manage, const QByteArray &json, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->post(request, json);
}

QNetworkReply *ENetwork::PostFile(QNetworkAccessManager *manage, QMap<QString, QString> files, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    QMap<QString, QString>::iterator it;
    QHttpMultiPart *mMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart filePart;
    QFile *file = new QFile(files["vistRecord"]);
    file->open(QFile::ReadOnly);

    filePart.setBodyDevice(file);                                                                                                                     // 这里的file对象就是我们需要提交的文件，如果需要上传多个文件，我们就需要创建多个QHttpPart对象
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream"));                                               // 这里我们上传的是图片
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"vistRecord\"; filename=\"" + file->fileName() + "\"")); // 这里的name默认情况下file，如果服务器那边有特别指定就需要改成服务器指定的名字
    mMultiPart->append(filePart);

    QNetworkRequest request;
    request.setUrl(QUrl(url));
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->post(request, mMultiPart);
}

QNetworkReply *ENetwork::Get(QNetworkAccessManager *manage, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    QNetworkRequest request;
    request.setUrl(QUrl::fromUserInput(url));
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->get(request);
}

QNetworkReply *ENetwork::Delete(QNetworkAccessManager *manage, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    QNetworkRequest request;
    request.setUrl(QUrl::fromUserInput(url));
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->deleteResource(request);
}

QNetworkReply *ENetwork::put(QNetworkAccessManager *manage, const QString &url, const QByteArray &httpTypeName, const QByteArray &httpTypeValue, bool needAuthenticated)
{
    if (manage == nullptr)
        return nullptr;
    QNetworkRequest request;
    request.setUrl(QUrl::fromUserInput(url));
    if (httpTypeName != "")
        request.setRawHeader(httpTypeName, httpTypeValue);
    if (needAuthenticated)
        request.setRawHeader(TOKENHEADNAME, token.toUtf8());
    return manage->put(request, "");
}

/**
 * @brief 根据设备序列号获取token，2023.05，王正猛和董海辉对token生成方法做了调整
 *
 * @param deviceSerial
 * @return QNetworkReply*
 */
// QNetworkReply *ENetwork::doLogin(QNetworkAccessManager *manage, const QByteArray &deviceSerial)
// {
//     if (manage == nullptr)
//         return nullptr;

//     QJsonObject jsonObj;
//     jsonObj.insert("deviceSerial", QJsonValue::fromVariant(deviceSerial));
//     const QByteArray &content = QJsonDocument(jsonObj).toJson();

//     int contentLength = content.length();
//     QNetworkRequest request;
//     request.setUrl(QUrl("http://testservice.ehanghai.cn/htz-api/prod/login/v1/device_login"));
//     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
//     request.setHeader(QNetworkRequest::ContentLengthHeader, contentLength);
//     request.setRawHeader("source", "htz-qt");
//     request.setRawHeader("version", "2023.05.10.0");
//     request.setRawHeader("ip", "192.168.18.126");
//     request.setRawHeader("reqId", "3daac5bb-9b9a-48bc-99d2-e2341402e3f9");

//     return manage->post(request, content);
// }
